Comparator vs Comparable

Java中对对象的集合或数组进行排序时通常有两种方式:Comparator && Comparable。

Comparable要求使用对象实现其compareTo方法来实现自定义的排序方式。
但在使用的场景中,往往在设计时并没有考虑到比较问题从而没有实现Comparable,这时候再去改造对象本身或许不太合适。

Comparator更加的灵活,采用的是策略模式,在不改变对象本身的情况下来改变对象的行为
举例说明:

class User {
    //年龄
    private Integer age;
    //身高
    private Integer height;
    //姓名
    private String name;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

现在需要给所有的User对象按年龄从小到大排序,如果年龄相同则按身高由高到低来排序。
以下是Comparable方式,通过改造User对象来实现自定义compileTo方法:

class User implements Comparable<User>{
    //年龄
    private Integer age;
    //身高
    private Integer height;
    //姓名
    private String name;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(User u) {
        int flag = this.age.compareTo(u.getAge());
        if (flag == 0 ) {
            return (this.height.compareTo(u.getHeight())) * -1;
        } else {
            return flag;
        }
    }
}

以下是Comparator的实现方法及测试类:

public class Test {
    public static void main(String[] args) {

        User user1 = new User();
        user1.setAge(20);
        user1.setHeight(180);
        user1.setName("张三");
        User user2 = new User();
        user2.setAge(20);
        user2.setHeight(176);
        user2.setName("李四");
        User user3 = new User();
        user3.setAge(25);
        user3.setHeight(155);
        user3.setName("王二");
        User user4 = new User();
        user4.setAge(23);
        user4.setHeight(155);
        user4.setName("麻子");
        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        //使用Comparator实现排序
        Collections.sort(userList, new Comparator<User>() {
            @Override
            public int compare(User u1, User u2) {
                int flag = u1.getAge().compareTo(u2.getAge());
                if (flag == 0) {
                    //身高降序
                    return (u1.getHeight().compareTo(u2.getHeight())) * -1;
                } else {
                    return flag;
                }
            }

        });

        //如果使用Comparable方式,可直接使用以下方式排序即可
        Collections.sort(userList);

        for (User u : userList) {
            System.out.println("姓名:"+u.getName()+",年龄:"+u.getAge()+",身高:"+u.getHeight());
        }

    }

}

结果:

姓名:张三,年龄:20,身高:180
姓名:李四,年龄:20,身高:176
姓名:麻子,年龄:23,身高:155
姓名:王二,年龄:25,身高:155

达到的效果一致,但是,这并没有结束。
在Java规范里,倡导保证equals和compareTo的行为一致,这样可以避免出现一些奇奇怪怪的问题。大致意思就是如果user1.compareTo(user2) == 0 的话,user1.equals(user2) == 1
既然重载了equals,那意味着hashcode也得重载了~ 你懂的